home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / muds / lpmud312.tar / lpmud312 / lex.c < prev    next >
C/C++ Source or Header  |  1991-12-12  |  34KB  |  1,687 lines

  1. #include <stdio.h>
  2. #include <ctype.h>
  3. #include <string.h>
  4.  
  5. #include "instrs.h"
  6. #include "lint.h"
  7. #include "lang.h"
  8. #include "string.h"
  9. #include "config.h"
  10. #include "interpret.h"
  11. #include "exec.h"
  12. #include "lex.h"
  13.  
  14. #if defined(__GNUC__) && !defined(lint)
  15. #define INLINE inline
  16. #else
  17. #define INLINE
  18. #endif
  19.  
  20. #define isalunum(c) (isalnum(c) || (c) == '_')
  21. #define NELEM(a) (sizeof (a) / sizeof (a)[0])
  22.  
  23. int current_line;
  24. int total_lines;    /* Used to compute average compiled lines/s */
  25. char *current_file;
  26. int pragma_strict_types;    /* Force usage of strict types. */
  27. int pragma_save_types;        /* Save argument types after compilation */
  28. struct lpc_predef_s *lpc_predefs=NULL;
  29. extern char *argument_name;
  30. extern char *xalloc();
  31. static int number PROT((int)), ident PROT((char *)), string PROT((char *));
  32. static int islocal PROT((char *));
  33. static void handle_define PROT((char *));
  34. static void free_defines PROT((void)), add_define PROT((char *, int, char *));
  35. static int expand_define PROT((void));
  36. static void add_input PROT((char *));
  37. static void myungetc PROT((int));
  38. static int lookup_resword PROT((char *));
  39. static int cond_get_exp PROT((int));
  40. static int exgetc();
  41. static FILE *yyin;
  42. static int lex_fatal;
  43. static char **inc_list;
  44. static int inc_list_size;
  45.  
  46. #define EXPANDMAX 25000
  47. static int nexpands;
  48.  
  49. extern char *local_names[];
  50. extern int current_number_of_locals;
  51.  
  52. extern char *string_copy();
  53.  
  54. #ifndef tolower
  55. extern int tolower PROT((int));
  56. #endif
  57.  
  58. void yyerror(), error(), free();
  59.  
  60. #define MAXLINE 1024
  61. static char yytext[MAXLINE];
  62. static int slast, lastchar;
  63.  
  64. struct defn {
  65.     struct defn *next;
  66.     char *name;
  67.     int undef;
  68.     char *exps;
  69.     int nargs;
  70. };
  71. struct defn *lookup_define();
  72.  
  73. static struct ifstate {
  74.     struct ifstate *next;
  75.     int state;
  76. } *iftop = 0;
  77. #define EXPECT_ELSE 1
  78. #define EXPECT_ENDIF 2
  79.  
  80. static struct incstate {
  81.     struct incstate *next;
  82.     FILE *yyin;
  83.     int line;
  84.     char *file;
  85.     int slast, lastchar;
  86.     int pragma_strict_types;
  87. } *inctop = 0;
  88.  
  89. #define DEFMAX 10000
  90. static char defbuf[DEFMAX];
  91. static int nbuf;
  92. static char *outp;
  93.  
  94. void merge(name, dest)
  95.     char *name, *dest;
  96. {
  97.     char *from;
  98.  
  99.     strcpy(dest, current_file);
  100.     if (from = strrchr(dest, '/'))   /* strip filename */
  101.     *from = 0;
  102.     else
  103.     /* current_file was the file_name */
  104.     /* include from the root directory */
  105.     *dest = 0;
  106.  
  107.     from = name;
  108.     while (*from == '/') {
  109.     from++;
  110.     *dest=0;    /* absolute path */
  111.     }
  112.  
  113.     while(*from) {
  114.     if(!strncmp(from, "../", 3)) {
  115.         char *tmp;
  116.         
  117.         if(*dest == 0) /* including from above mudlib is NOT allowed */
  118.         break;
  119.         tmp = strrchr(dest, '/');
  120.         if(tmp == NULL) /* 1 component in dest */
  121.         *dest = 0;
  122.         else
  123.         *tmp = 0;
  124.         from +=3;   /* skip "../" */
  125.     }
  126.     else if(!strncmp(from, "./", 2)) {
  127.         from += 2;
  128.     }
  129.     else { /* append first component to dest */
  130.         char *q;
  131.         
  132.         if(*dest)
  133.         strcat(dest, "/");    /* only if dest is not empty !! */
  134.         q = strchr(from, '/');
  135.         
  136.         if(q) { /* from has 2 or more components */
  137.         while(*from=='/') /* find the start */
  138.             from++;
  139.         strncat(dest, from, q - from);
  140.         for(from = q+1;*from=='/';from++)
  141.             ;
  142.         }
  143.         else {
  144.         /* this was the last component */
  145.         strcat(dest, from);
  146.         break;
  147.         }
  148.     }
  149.     }
  150. }
  151.  
  152. static INLINE int
  153. mygetc()
  154. {
  155.     int c;
  156.  
  157.     if (nbuf) {
  158.     nbuf--;
  159.     c = *outp++;
  160.     } else {
  161.     c = getc(yyin);
  162.     }
  163.     lastchar = slast;
  164.     slast = c;
  165. /*fprintf(stderr, "c='%c'", c);*/
  166.     return c;
  167. }
  168.  
  169. static INLINE int
  170. gobble(c)
  171. int c;
  172. {
  173.     int d;
  174.     d = mygetc();
  175.     if (c == d)
  176.     return 1;
  177.     *--outp = d;
  178.     nbuf++;
  179.     return 0;
  180. }
  181.  
  182. static void
  183. lexerror(s)
  184. char *s;
  185. {
  186.     yyerror(s);
  187.     lex_fatal++;
  188. }
  189.  
  190. static int
  191. skip_to(token, atoken)
  192. char *token, *atoken;
  193. {
  194.     char b[20], *p;
  195.     int c;
  196.     int nest;
  197.  
  198.     for(nest = 0;;) {
  199.     c = mygetc();
  200.     if (c == '#') {
  201.         do {
  202.         c = mygetc();
  203.         } while(isspace(c));
  204.         for(p = b; c != '\n' && c != EOF; ) {
  205.         if (p < b+sizeof b-1)
  206.             *p++ = c;
  207.         c = mygetc();
  208.         }
  209.         *p++ = 0;
  210.         for(p = b; *p && !isspace(*p); p++)
  211.         ;
  212.         *p = 0;
  213. /*fprintf(stderr, "skip checks %s\n", b);*/
  214.         if (strcmp(b, "if") == 0 || strcmp(b, "ifdef") == 0 ||
  215.         strcmp(b, "ifndef") == 0) {
  216.         nest++;
  217.         } else if (nest > 0) {
  218.         if (strcmp(b, "endif") == 0)
  219.             nest--;
  220.         } else {
  221.         if (strcmp(b, token) == 0)
  222.             return 1;
  223.         else if (atoken && strcmp(b, atoken) == 0)
  224.             return 0;
  225.         }
  226.     } else {
  227. /*fprintf(stderr, "skipping (%d) %c", c, c);*/
  228.             while (c != '\n' && c != EOF) {
  229.         c = mygetc();
  230. /*fprintf(stderr, "%c", c);*/
  231.         } 
  232.         if (c == EOF) {
  233.         lexerror("Unexpected end of file while skipping");
  234.         return 1;
  235.         }
  236.     }
  237.     if (inctop == 0)
  238.         store_line_number_info();
  239.     current_line++;
  240.     total_lines++;
  241.     }
  242. }
  243.  
  244. static void
  245. handle_cond(c)
  246. int c;
  247. {
  248.     struct ifstate *p;
  249.  
  250. /*fprintf(stderr, "cond %d\n", c);*/
  251.     if (c || skip_to("else", "endif")) {
  252.     p = (struct ifstate *)xalloc(sizeof(struct ifstate));
  253.     p->next = iftop;
  254.     iftop = p;
  255.     p->state = c ? EXPECT_ELSE : EXPECT_ENDIF;
  256.     }
  257.     if (!c) {
  258.     if (inctop == 0)
  259.         store_line_number_info();
  260.     current_line++;
  261.     total_lines++;
  262.     }
  263. }
  264.  
  265. static FILE *
  266. inc_open(buf, name)
  267.     char *buf, *name;
  268. {
  269.     FILE *f;
  270.     int i;
  271.     char *p;
  272.  
  273.     merge(name, buf);
  274.     if ((f = fopen(buf, "r")) != NULL)
  275.     return f;
  276.     /*
  277.      * Search all include dirs specified.
  278.      */
  279.     for (p=strchr(name, '.'); p; p = strchr(p+1, '.')) {
  280.     if (p[1] == '.')
  281.         return NULL;
  282.     }
  283.     for (i=0; i < inc_list_size; i++) {
  284.     sprintf(buf, inc_list[i], name);
  285.     f = fopen(buf, "r");
  286.     if (f)
  287.         return f;
  288.     }
  289.     return NULL;
  290. }
  291.  
  292. static void
  293. handle_include(name)
  294. char *name;
  295. {
  296.     char *p;
  297.     char buf[1024];
  298.     FILE *f;
  299.     struct incstate *is;
  300.     int delim;
  301.  
  302. /*fprintf(stderr, "handle include '%s'\n", name);*/
  303.     if (nbuf) {
  304.     lexerror("Internal preprocessor error");
  305.     return;
  306.     }
  307.     if (*name != '"' && *name != '<') {
  308.     struct defn *d;
  309.     if ((d = lookup_define(name)) && d->nargs == -1) {
  310.         char *q;
  311.         q = d->exps;
  312.         while(isspace(*q))
  313.         q++;
  314.         handle_include(q);
  315.     } else {
  316.         yyerror("Missing leading \" or < in #include");
  317.     }
  318.     return;
  319.     }
  320.     delim = *name++ == '"' ? '"' : '>';
  321.     for(p = name; *p && *p != delim; p++)
  322.     ;
  323.     if (!*p) {
  324.     yyerror("Missing trailing \" or > in #include");
  325.     return;
  326.     }
  327.     if (strlen(name) > sizeof(buf) - 100) {
  328.     yyerror("Include name too long.");
  329.     return;
  330.     }
  331.     *p = 0;
  332.     if ((f = inc_open(buf, name)) != NULL) {
  333.     is = (struct incstate *)xalloc(sizeof(struct incstate));
  334.     is->yyin = yyin;
  335.     is->line = current_line;
  336.     is->file = current_file;
  337.     is->slast = slast;
  338.     is->lastchar = lastchar;
  339.     is->next = inctop;
  340.     is->pragma_strict_types = pragma_strict_types;
  341.     pragma_strict_types = 0;
  342.     inctop = is;
  343.     current_line = 1;
  344.     current_file = xalloc(strlen(buf)+1);
  345.     strcpy(current_file, buf);
  346.     slast = lastchar = '\n';
  347.     yyin = f;
  348. /*fprintf(stderr, "pushed to %s\n", buf);*/
  349.     } else {
  350.     sprintf(buf, "Cannot #include %s\n", name);
  351.     yyerror(buf);
  352.     }
  353. }
  354.  
  355. static void
  356. skip_comment()
  357. {
  358.     int c;
  359.  
  360.     for(;;) {
  361.     while((c = mygetc()) != '*') {
  362.         if (c == EOF) {
  363.             lexerror("End of file in a comment");
  364.         return;
  365.         }
  366.         if (c == '\n') {
  367.         if (inctop == 0)
  368.             store_line_number_info();
  369.         nexpands=0;
  370.         current_line++;
  371.         }
  372.     }
  373.     do {
  374.         if ((c = mygetc()) == '/')
  375.         return;
  376.         if (c == '\n') {
  377.         if (inctop == 0)
  378.             store_line_number_info();
  379.         nexpands=0;
  380.         current_line++;
  381.         }
  382.     } while(c == '*');
  383.     }
  384. }
  385.  
  386. #define TRY(c, t) if (gobble(c)) return t
  387.  
  388. static void
  389. deltrail(sp)
  390. char *sp;
  391. {
  392.     char *p;
  393.     p = sp;
  394.     if (!*p) {
  395.     lexerror("Illegal # command");
  396.     } else {
  397.     while(*p && !isspace(*p))
  398.         p++;
  399.     *p = 0;
  400.     }
  401. }
  402.  
  403. #define SAVEC \
  404.     if (yyp < yytext+MAXLINE-5)\
  405.        *yyp++ = c;\
  406.     else {\
  407.        lexerror("Line too long");\
  408.        break;\
  409.     }
  410.  
  411. static void handle_pragma(str)
  412.     char *str;
  413. {
  414.     if (strcmp(str, "strict_types") == 0) {
  415.     pragma_strict_types = 1;
  416.     } else if (strcmp(str, "save_types") == 0) {
  417.     pragma_save_types = 1;
  418.     }
  419. }
  420.  
  421. static int
  422. yylex1()
  423. {
  424.   register char *yyp;
  425.   register int c;
  426.  
  427.   for(;;) {
  428.     if (lex_fatal) {
  429.     return -1;
  430.     }
  431.     switch(c = mygetc()) {
  432.     case EOF:
  433.     if (inctop) {
  434.         struct incstate *p;
  435.         p = inctop;
  436.         fclose(yyin);
  437. /*fprintf(stderr, "popping to %s\n", p->file);*/
  438.         free(current_file);
  439.         nexpands=0;
  440.         current_file = p->file;
  441.         current_line = p->line + 1;
  442.         pragma_strict_types = p->pragma_strict_types;
  443.         yyin = p->yyin;
  444.         slast = p->slast;
  445.         lastchar = p->lastchar;
  446.         inctop = p->next;
  447.         if (inctop == 0)
  448.         store_line_number_info();
  449.         free((char *)p);
  450.         break;
  451.     }
  452.     if (iftop) {
  453.         struct ifstate *p = iftop;
  454.         yyerror(p->state == EXPECT_ENDIF ? "Missing #endif" : "Missing #else");
  455.         while(iftop) {
  456.         p = iftop;
  457.         iftop = p->next;
  458.         free((char *)p);
  459.         }
  460.     }
  461.     return -1;
  462.     case '\n':
  463.     {
  464.         if (inctop == 0)
  465.         store_line_number_info();
  466.         nexpands=0;
  467.         current_line++;
  468.         total_lines++;
  469.     }
  470.     case ' ':
  471.     case '\t':
  472.     case '\f':
  473.     case '\v':
  474.     break;
  475.     case '+':
  476.     TRY('+', F_INC);
  477.     TRY('=', F_ADD_EQ);
  478.     return c;
  479.     case '-':
  480.     TRY('>', F_ARROW);
  481.     TRY('-', F_DEC);
  482.     TRY('=', F_SUB_EQ);
  483.     return c;
  484.     case '&':
  485.     TRY('&', F_LAND);
  486.     TRY('=', F_AND_EQ);
  487.     return c;
  488.     case '|':
  489.     TRY('|', F_LOR);
  490.     TRY('=', F_OR_EQ);
  491.     return c;
  492.     case '^':
  493.     TRY('=', F_XOR_EQ);
  494.     return c;
  495.     case '<':
  496.     if (gobble('<')) {
  497.         TRY('=', F_LSH_EQ);
  498.         return F_LSH;
  499.     }
  500.     TRY('=', F_LE);
  501.     return c;
  502.     case '>':
  503.     if (gobble('>')) {
  504.         TRY('=', F_RSH_EQ);
  505.         return F_RSH;
  506.     }
  507.     TRY('=', F_GE);
  508.     return c;
  509.     case '*':
  510.     TRY('=', F_MULT_EQ);
  511.     return c;
  512.     case '%':
  513.     TRY('=', F_MOD_EQ);
  514.     return c;
  515.     case '/':
  516.     if (gobble('*')) {
  517.         skip_comment();
  518.         break;
  519.         }
  520.     TRY('=', F_DIV_EQ);
  521.     return c;
  522.     case '=':
  523.     TRY('=', F_EQ);
  524.     return c;
  525.     case ';':
  526.     case '(':
  527.     case ')':
  528.     case ',':
  529.     case '{':
  530.     case '}':
  531.     case '~':
  532.     case '[':
  533.     case ']':
  534.     case '?':
  535.     return c;
  536.     case '!':
  537.     TRY('=', F_NE);
  538.     return F_NOT;
  539.     case ':':
  540.     TRY(':', F_COLON_COLON);
  541.     return ':';
  542.     case '.':
  543.     TRY('.',F_RANGE);
  544.     goto badlex;
  545.     case '#':
  546.     if (lastchar == '\n') {
  547.         char *sp = 0;
  548.         int quote;
  549.  
  550.         yyp = yytext;
  551.         do {
  552.         c = mygetc();
  553.         } while (isspace(c));
  554.         for(quote = 0;;) {
  555.  
  556.         if (c == '"')
  557.             quote ^= 1;
  558.         while(!quote && c == '/') { /*gc - handle comments cpp-like! 1.6.91 @@@*/
  559.             if(gobble('*')) { 
  560.             skip_comment();
  561.             c=mygetc();
  562.             } else 
  563.             break;
  564.         }
  565.  
  566.         if (!sp && isspace(c))
  567.             sp = yyp;
  568.         if (c == '\n' || c == EOF)
  569.             break;
  570.         SAVEC;
  571.         c = mygetc();
  572.         }
  573.         if (sp) {
  574.         *sp++ = 0;
  575.         while(isspace(*sp))
  576.             sp++;
  577.         } else {
  578.         sp = yyp;
  579.         }
  580.         *yyp = 0;
  581.         if (strcmp("define", yytext) == 0) {
  582.         handle_define(sp);
  583.         } else if (strcmp("if", yytext) == 0) {
  584. #if 0
  585.         short int nega=0; /*@@@ allow #if !VAR gc 1.6.91*/
  586.         if (*sp=='!'){ sp++; nega=1;}
  587.         if (isdigit(*sp)) {
  588.             char *p;
  589.             long l;
  590.             l = strtol(sp, &p, 10);
  591.             while(isspace(*p))
  592.             p++;
  593.             if (*p)
  594.             yyerror("Condition too complex in #if");
  595.             else
  596.             handle_cond(nega?!(int)l:(int)l);
  597.         } else if (isalunum(*sp)) {
  598.             char *p = sp;
  599.             while(isalunum(*p))
  600.             p++;
  601.             if (*p) {
  602.             *p++ = 0;
  603.             while(isspace(*p))
  604.                 p++;
  605.             }
  606.             if (*p)
  607.             yyerror("Condition too complex in #if");
  608.             else {
  609.             struct defn *d;
  610.             d = lookup_define(sp);
  611.             if (d) {
  612.                 handle_cond(nega?!atoi(d->exps):atoi(d->exps));/* a hack! */
  613.             } else {
  614.                 handle_cond(nega?1:0); /* cpp-like gc*/
  615.             }
  616.             }
  617.         } else
  618.             yyerror("Condition too complex in #if");
  619. #else
  620.         int cond;
  621.  
  622.         myungetc(0);
  623.         add_input(sp);
  624.         cond=cond_get_exp(0);
  625.         if (mygetc()) {
  626.             yyerror("Condition too complex in #if");
  627.             while ( mygetc() ) ;
  628.         } else
  629.             handle_cond(cond);
  630. #endif
  631.         } else if (strcmp("ifdef", yytext) == 0) {
  632.         deltrail(sp);
  633.         handle_cond(lookup_define(sp) != 0);
  634.         } else if (strcmp("ifndef", yytext) == 0) {
  635.         deltrail(sp);
  636.         handle_cond(lookup_define(sp) == 0);
  637.         } else if (strcmp("else", yytext) == 0) {
  638.         if (iftop && iftop->state == EXPECT_ELSE) {
  639.             struct ifstate *p = iftop;
  640.  
  641. /*fprintf(stderr, "found else\n");*/
  642.             iftop = p->next;
  643.             free((char *)p);
  644.             skip_to("endif", (char *)0);
  645.             current_line++;
  646.             total_lines++;
  647.         } else {
  648.             yyerror("Unexpected #else");
  649.         }
  650.         } else if (strcmp("endif", yytext) == 0) {
  651.         if (iftop && (iftop->state == EXPECT_ENDIF ||
  652.                   iftop->state == EXPECT_ELSE)) {
  653.             struct ifstate *p = iftop;
  654.  
  655. /*fprintf(stderr, "found endif\n");*/
  656.             iftop = p->next;
  657.             free((char *)p);
  658.         } else {
  659.             yyerror("Unexpected #endif");
  660.         }
  661.         } else if (strcmp("undef", yytext) == 0) {
  662.         struct defn *d;
  663.  
  664.         deltrail(sp);
  665.         if (d = lookup_define(sp))
  666.             d->undef++;
  667.         } else if (strcmp("echo", yytext) == 0) {
  668.         fprintf(stderr, "%s\n", sp);
  669.         } else if (strcmp("include", yytext) == 0) {
  670. /*fprintf(stderr, "including %s\n", sp);        */
  671.                 handle_include(sp);
  672.         } else if (strcmp("pragma", yytext) == 0) {
  673.         handle_pragma(sp);
  674.         } else {
  675.         yyerror("Unrecognised # directive");
  676.         }
  677.         myungetc('\n');
  678.         break;
  679.     } else
  680.         goto badlex;
  681.     case '\'':
  682.     yylval.number = mygetc();
  683.     if (yylval.number == '\\')
  684.         yylval.number = mygetc();
  685.     if (!gobble('\''))
  686.         yyerror("Illegal character constant");
  687.     return F_NUMBER;
  688.     case '"':
  689.     yyp = yytext;
  690.     *yyp++ = c;
  691.     for(;;) {
  692.         c = mygetc();
  693.         if (c == EOF) {
  694.          lexerror("End of file in string");
  695.         return string("\"\"");
  696.         } else if (c == '\n') {
  697.          lexerror("Newline in string");
  698.         return string("\"\"");
  699.         }
  700.         SAVEC;
  701.         if (c == '"')
  702.         break;
  703.         if (c == '\\') {
  704.         c = mygetc();
  705.         if ( c == '\n' ) {
  706.             yyp--;
  707.             if (inctop == 0)
  708.                 store_line_number_info();
  709.             current_line++;
  710.             total_lines++;
  711.         } else if ( c == EOF ) {
  712.             myungetc(c); /* some operating systems give EOF only once */
  713.         } else *yyp++ = c;
  714.         }
  715.     }
  716.     *yyp = 0;
  717.     return string(yytext);
  718.  
  719.     case '0':
  720.     c = mygetc();
  721.     if ( c == 'X' || c == 'x' ) {
  722.         yyp=yytext;
  723.         for(;;) {
  724.         c = mygetc();
  725.         SAVEC;
  726.         if (!isxdigit(c))
  727.             break;
  728.         }
  729.         myungetc(c);
  730.         return number( (int)strtol(yytext,(char**)NULL,0x10) );
  731.     }
  732.     myungetc(c);
  733.     c = '0';
  734.     /* fall through */
  735.              case '1':case '2':case '3':case '4':
  736.     case '5':case '6':case '7':case '8':case '9':
  737.     yyp = yytext;
  738.     *yyp++ = c;
  739.     for(;;) {
  740.         c = mygetc();
  741.         if (!isdigit(c))
  742.         break;
  743.         SAVEC;
  744.     }
  745.     myungetc(c);
  746.     *yyp = 0;
  747.     return number(atoi(yytext));
  748.     default:
  749.     if (isalpha(c) || c == '_') {
  750.         int r;
  751.  
  752.         yyp = yytext;
  753.         *yyp++ = c;
  754.         for(;;) {
  755.         c = mygetc();
  756.         if (!isalunum(c))
  757.             break;
  758.         SAVEC;
  759.         }
  760.         *yyp = 0;
  761.  
  762.         myungetc(c);
  763.         if (!expand_define()) {
  764.         r = lookup_resword(yytext);
  765.         if (r >= 0) {
  766.             return r;
  767.         } else
  768.             return ident(yytext);
  769.         }
  770.         break;
  771.         }
  772.     goto badlex;
  773.     }
  774.   }
  775.  badlex:
  776.   { char buff[100]; sprintf(buff, "Illegal character (hex %02x) '%c'", c, c);
  777.     yyerror(buff); return ' '; }
  778. }
  779.  
  780. int
  781. yylex()
  782. {
  783.     int r;
  784.  
  785.     yytext[0] = 0;
  786.     r = yylex1();
  787. /*    fprintf(stderr, "lex=%d(%s) ", r, yytext);*/
  788.     return r;
  789. }
  790.  
  791. extern YYSTYPE yylval;
  792.  
  793. static int islocal(str)
  794.     char *str;
  795. {
  796.     int i;
  797.  
  798.     for (i=current_number_of_locals-1; i>=0; i--) {
  799.     if (strcmp(local_names[i], str) == 0)
  800.             return i;
  801.     }
  802.     return -1;
  803. }
  804.  
  805. static int ident(str)
  806.     char *str;
  807. {
  808.     int i;
  809.    
  810.     i = islocal(str);
  811.     if (i >= 0) {
  812.         yylval.number = i;
  813.         return F_LOCAL_NAME;
  814.     }
  815.     yylval.string = string_copy(str);
  816.     return F_IDENTIFIER;
  817. }
  818.  
  819. static int string(str)
  820.     char *str;
  821. {
  822.     char *p;
  823.  
  824.     if (!*str) {
  825.     str = "\"\"";
  826.     }
  827.     p = xalloc(strlen(str));
  828.     yylval.string = p;
  829.     for (str++; str[0] && str[1] ; str++, p++) {
  830.     if (str[0] == '\\') {
  831.         if (str[1] == 'n') {
  832.         *p = '\n';
  833.         } else if (str[1] == 't') {
  834.         *p = '\t';
  835.         } else if (str[1] == 'r') {
  836.         *p = '\r';
  837.         } else if (str[1] == 'b') {
  838.         *p = '\b';
  839.         } else
  840.         *p = str[1];
  841.         str++;
  842.     } else
  843.         *p = *str;
  844.     }
  845.     *p = '\0';
  846.     return F_STRING;
  847. }
  848.  
  849. static int number(i)
  850.     int i;
  851. {
  852.     yylval.number = i;
  853.     return F_NUMBER;
  854. }
  855.  
  856. void end_new_file()
  857. {
  858.     while (inctop) {
  859.     struct incstate *p;
  860.     p = inctop;
  861.     fclose(yyin);
  862.     free(current_file);
  863.     current_file = p->file;
  864.     yyin = p->yyin;
  865.     inctop = p->next;
  866.     free((char *)p);
  867.     }
  868.     while(iftop) {
  869.     struct ifstate *p;
  870.  
  871.     p = iftop;
  872.     iftop = p->next;
  873.     free((char *)p);
  874.     }
  875. }
  876.  
  877. void start_new_file(f)
  878.     FILE *f;
  879. {
  880.     struct lpc_predef_s *tmpf;
  881.  
  882.     free_defines();
  883.     add_define("LPC3", -1, "");
  884. #ifdef COMPAT_MODE
  885.     add_define("COMPAT_FLAG", -1, "");
  886. #endif
  887.     for (tmpf=lpc_predefs; tmpf; tmpf=tmpf->next) {
  888.     char namebuf[NSIZE];
  889.     char mtext[MLEN];
  890.  
  891.     *mtext='\0';
  892.     sscanf(tmpf->flag,"%[^=]=%[ -~=]",namebuf,mtext);
  893.     if ( strlen(namebuf) >= NSIZE ) fatal("NSIZE exceeded");
  894.     if ( strlen(mtext) >= MLEN ) fatal("MLEN exceeded");
  895.     add_define(namebuf,-1,mtext);
  896.     }
  897.     yyin = f;
  898.     slast = '\n';
  899.     lastchar = '\n';
  900.     current_line = 1;
  901.     lex_fatal = 0;
  902.     nbuf = 0;
  903.     outp = defbuf+DEFMAX;
  904.     pragma_strict_types = 0;        /* I would prefer !o_flag   /Lars */
  905.     nexpands = 0;
  906. }
  907.  
  908. /*
  909.  * The number of arguments stated below, are used by the compiler.
  910.  * If min == max, then no information has to be coded about the
  911.  * actual number of arguments. Otherwise, the actual number of arguments
  912.  * will be stored in the byte after the instruction.
  913.  * A maximum value of -1 means unlimited maximum value.
  914.  *
  915.  * If an argument has type 0 (T_INVALID) specified, then no checks will
  916.  * be done at run time.
  917.  *
  918.  * The argument types are currently not checked by the compiler,
  919.  * only by the runtime.
  920.  */
  921. static struct keyword {
  922.     char *word;
  923.     short  token;
  924.     short min_args;    /* Minimum number of arguments. */
  925.     short max_args;    /* Maximum number of arguments. */
  926.     short ret_type;    /* The return type used by the compiler. */
  927.     char arg_type1;    /* Type of argument 1 */
  928.     char arg_type2;    /* Type of argument 2 */
  929.     char arg_index;    /* Index pointing to where to find arg type */
  930.     short Default;      /* an efun to use as default for last argument */
  931. } predefs[] =
  932. #include "efun_defs.c"
  933.  
  934. static struct keyword reswords[] = {
  935. { "break",        F_BREAK, },
  936. { "case",        F_CASE, },
  937. { "catch",        F_CATCH, },
  938. { "continue",        F_CONTINUE, },
  939. { "default",        F_DEFAULT, },
  940. { "do",            F_DO, },
  941. { "else",        F_ELSE, },
  942. { "for",        F_FOR, },
  943. { "if",            F_IF, },
  944. { "inherit",        F_INHERIT, },
  945. { "int",        F_INT, },
  946. { "mixed",        F_MIXED, },
  947. { "nomask",        F_NO_MASK, },
  948. { "object",        F_OBJECT, },
  949. { "parse_command",    F_PARSE_COMMAND, },
  950. { "private",        F_PRIVATE, },
  951. { "protected",        F_PROTECTED, },
  952. { "public",        F_PUBLIC, },
  953. { "return",        F_RETURN, },
  954. { "sscanf",        F_SSCANF, },
  955. { "static",        F_STATIC, },
  956. { "status",        F_STATUS, },
  957. { "string",        F_STRING_DECL, },
  958. { "switch",        F_SWITCH, },
  959. { "varargs",        F_VARARGS, },
  960. { "void",        F_VOID, },
  961. { "while",        F_WHILE, },
  962. };
  963.  
  964. struct instr instrs[256];
  965.  
  966. static void add_instr_name(name, n)
  967.     char *name;
  968.     int n;
  969. {
  970.     instrs[n - F_OFFSET].name = name;
  971. }
  972.  
  973. void init_num_args()
  974. {
  975.     int i, n;
  976.  
  977.     for(i=0; i<NELEM(predefs); i++) {
  978.     n = predefs[i].token - F_OFFSET;
  979.     if (n < 0 || n > NELEM(instrs))
  980.         fatal("Token %s has illegal value %d.\n", predefs[i].word, n);
  981.     instrs[n].min_arg = predefs[i].min_args;
  982.     instrs[n].max_arg = predefs[i].max_args;
  983.     instrs[n].name = predefs[i].word;
  984.     instrs[n].type[0] = predefs[i].arg_type1;
  985.     instrs[n].type[1] = predefs[i].arg_type2;
  986.     instrs[n].Default = predefs[i].Default;
  987.     instrs[n].ret_type = predefs[i].ret_type;
  988.     instrs[n].arg_index = predefs[i].arg_index;
  989.     }
  990.     add_instr_name("<", F_LT);
  991.     add_instr_name(">", F_GT);
  992.     add_instr_name("<=", F_LE);
  993.     add_instr_name(">=", F_GE);
  994.     add_instr_name("==", F_EQ);
  995.     add_instr_name("+=", F_ADD_EQ);
  996.     add_instr_name("!", F_NOT);
  997.     add_instr_name("index", F_INDEX);
  998.     add_instr_name("push_indexed_lvalue", F_PUSH_INDEXED_LVALUE);
  999.     add_instr_name("identifier", F_IDENTIFIER);
  1000.     add_instr_name("local", F_LOCAL_NAME);
  1001.     add_instr_name("indirect", F_INDIRECT);
  1002.     add_instr_name("number", F_NUMBER);
  1003.     add_instr_name("push_local_variable_lvalue", F_PUSH_LOCAL_VARIABLE_LVALUE);
  1004.     add_instr_name("const1", F_CONST1);
  1005.     add_instr_name("subtract", F_SUBTRACT);
  1006.     add_instr_name("assign", F_ASSIGN);
  1007.     add_instr_name("pop", F_POP_VALUE);
  1008.     add_instr_name("const0", F_CONST0);
  1009.     add_instr_name("jump_when_zero", F_JUMP_WHEN_ZERO);
  1010.     add_instr_name("jump_when_non_zero", F_JUMP_WHEN_NON_ZERO);
  1011.     add_instr_name("||", F_LOR);
  1012.     add_instr_name("&&", F_LAND);
  1013.     add_instr_name("-=", F_SUB_EQ);
  1014.     add_instr_name("jump", F_JUMP);
  1015.     add_instr_name("return", F_RETURN);
  1016.     add_instr_name("sscanf", F_SSCANF);
  1017.     add_instr_name("string", F_STRING);
  1018.     add_instr_name("call", F_CALL_FUNCTION_BY_ADDRESS);
  1019.     add_instr_name("aggregate", F_AGGREGATE);
  1020.     add_instr_name("push_identifier_lvalue", F_PUSH_IDENTIFIER_LVALUE);
  1021.     add_instr_name("+", F_ADD);
  1022.     add_instr_name("!=", F_NE);
  1023.     add_instr_name("dup", F_DUP);
  1024.     add_instr_name("catch", F_CATCH);
  1025.     add_instr_name("neg", F_NEGATE);
  1026.     add_instr_name("x++", F_POST_INC);
  1027.     add_instr_name("x--", F_POST_DEC);
  1028.     add_instr_name("switch",F_SWITCH);
  1029.     add_instr_name("break",F_BREAK);
  1030.     add_instr_name("range",F_RANGE);
  1031.     instrs[F_RANGE-F_OFFSET].type[0] = T_POINTER|T_STRING;
  1032. }
  1033.  
  1034. char *get_f_name(n)
  1035.     int n;
  1036. {
  1037.     if (instrs[n-F_OFFSET].name)
  1038.     return instrs[n-F_OFFSET].name;
  1039.     else {
  1040.     static char buf[30];
  1041.     sprintf(buf, "<OTHER %d>", n);
  1042.     return buf;
  1043.     }
  1044. }
  1045.  
  1046. static int
  1047. lookupword(s, words, h)
  1048. char *s;
  1049. struct keyword *words;
  1050. int h;
  1051. {
  1052.     int i, l, r;
  1053.  
  1054.     l = 0;
  1055.     for(;;) {
  1056.       i = (l+h)/2;
  1057.       r = strcmp(s, words[i].word);
  1058.       if (r == 0)
  1059.           return words[i].token;
  1060.       else if (l == i)
  1061.           return -1;
  1062.       else if (r < 0)
  1063.           h = i;
  1064.       else
  1065.           l = i;
  1066.     }
  1067. }
  1068.  
  1069. static int lookup_resword(s)
  1070.     char *s;
  1071. {
  1072.     return lookupword(s, reswords, NELEM(reswords));
  1073. }
  1074.  
  1075. int lookup_predef(s)
  1076.     char *s;
  1077. {
  1078.     return lookupword(s, predefs, NELEM(predefs));
  1079. }
  1080.  
  1081. #define NARGS 25
  1082. #define MARKS '@'
  1083.  
  1084. #define SKIPWHITE while(isspace(*p)) p++
  1085. #define GETALPHA(p, q, m) \
  1086.     while(isalunum(*p)) {\
  1087.     *q = *p++;\
  1088.     if (q < (m))\
  1089.         q++;\
  1090.     else {\
  1091.         lexerror("Name too long");\
  1092.         return;\
  1093.     }\
  1094.     }\
  1095.     *q++ = 0
  1096.  
  1097. static int
  1098. cmygetc()
  1099. {
  1100.     int c;
  1101.  
  1102.     for(;;) {
  1103.     c = mygetc();
  1104.     if (c == '/') {
  1105.         if (gobble('*'))
  1106.         skip_comment();
  1107.         else
  1108.         return c;
  1109.     } else
  1110.         return c;
  1111.     }
  1112. }
  1113.  
  1114. static void
  1115. refill()
  1116. {
  1117.     char *p;
  1118.     int c;
  1119.  
  1120.     p = yytext;
  1121.     do {
  1122.     c = cmygetc();
  1123.     if (p < yytext+MAXLINE-5)
  1124.         *p++ = c;
  1125.     else {
  1126.         lexerror("Line too long");
  1127.         break;
  1128.     }
  1129.     } while(c != '\n' && c != EOF);
  1130.     p[-1] = ' ';
  1131.     *p = 0;
  1132.     nexpands=0;
  1133.     current_line++;
  1134.     if (inctop == 0)
  1135.     store_line_number_info();
  1136. }
  1137.  
  1138. static void
  1139. handle_define(yyt)
  1140. char *yyt;
  1141. {
  1142.     char namebuf[NSIZE];
  1143.     char args[NARGS][NSIZE];
  1144.     char mtext[MLEN];
  1145.     char *p, *q;
  1146.  
  1147.     p = yyt;
  1148.     strcat(p, " ");
  1149.     q = namebuf;
  1150.     GETALPHA(p, q, namebuf+NSIZE-1);
  1151.     if (*p == '(') {        /* if "function macro" */
  1152.     int arg;
  1153.     int inid;
  1154.     char *ids;
  1155.     p++;            /* skip '(' */
  1156.     SKIPWHITE;
  1157.     if (*p == ')') {
  1158.         arg = 0;
  1159.     } else {
  1160.         for(arg = 0; arg < NARGS; ) {
  1161.         q = args[arg];
  1162.         GETALPHA(p, q, args[arg]+NSIZE-1);
  1163.         arg++;
  1164.         SKIPWHITE;
  1165.         if (*p == ')')
  1166.             break;
  1167.         if (*p++ != ',') {
  1168.             yyerror("Missing ',' in #define parameter list");
  1169.             return;
  1170.         }
  1171.         SKIPWHITE;
  1172.         }
  1173.         if (arg == NARGS) {
  1174.         lexerror("Too many macro arguments");
  1175.         return;
  1176.         }
  1177.     }
  1178.     p++;            /* skip ')' */
  1179.     for(inid = 0, q = mtext; *p; ) {
  1180.         if (isalunum(*p)) {
  1181.         if (!inid) {
  1182.             inid++;
  1183.             ids = p;
  1184.         }
  1185.         } else {
  1186.         if (inid) {
  1187.             int idlen = p - ids;
  1188.             int n, l;
  1189.             for(n = 0; n < arg; n++) {
  1190.             l = strlen(args[n]);
  1191.             if (l == idlen && strncmp(args[n], ids, l) == 0) {
  1192.                 q -= idlen;
  1193.                 *q++ = MARKS;
  1194.                 *q++ = n+MARKS+1;
  1195.                 break;
  1196.             }
  1197.             }
  1198.             inid = 0;
  1199.         }
  1200.         }
  1201.         *q = *p;
  1202.         if (*p++ == MARKS)
  1203.         *++q = MARKS;
  1204.         if (q < mtext+MLEN-2)
  1205.         q++;
  1206.         else {
  1207.         lexerror("Macro text too long");
  1208.         return;
  1209.         }
  1210.         if (!*p && p[-2] == '\\') {
  1211.         q -= 2;
  1212.         refill();
  1213.         p = yytext;
  1214.         }
  1215.     }
  1216.     *--q = 0;
  1217.     add_define(namebuf, arg, mtext);
  1218.     } else {
  1219.     for(q = mtext; *p; ) {
  1220.         *q = *p++;
  1221.         if (q < mtext+MLEN-2)
  1222.         q++;
  1223.         else {
  1224.         lexerror("Macro text too long");
  1225.         return;
  1226.         }
  1227.         if (!*p && p[-2] == '\\') {
  1228.         q -= 2;
  1229.         refill();
  1230.         p = yytext;
  1231.         }
  1232.     }
  1233.     *--q = 0;
  1234.     add_define(namebuf, -1, mtext);
  1235.     }
  1236.     return;
  1237. }
  1238.  
  1239. static void
  1240. myungetc(c)
  1241. int c;
  1242. {
  1243.     *--outp = c;
  1244.     nbuf++;
  1245. }
  1246.  
  1247. static void
  1248. add_input(p)
  1249. char *p;
  1250. {
  1251.     int l = strlen(p);
  1252.  
  1253. /*if (l > 2)
  1254. fprintf(stderr, "add '%s'\n", p);*/
  1255.     if (nbuf+l >= DEFMAX-10) {
  1256.     lexerror("Macro expansion buffer overflow");
  1257.     return;
  1258.     }
  1259.     outp -= l;
  1260.     nbuf += l;
  1261.     strncpy(outp, p, l);
  1262. }
  1263.  
  1264. #define DEFHASH 33
  1265. struct defn *defns[DEFHASH];
  1266. #define defhash(s) hashstr(s, 10, DEFHASH)
  1267.  
  1268. static void
  1269. add_define(name, nargs, exps)
  1270. char *name, *exps;
  1271. int nargs;
  1272. {
  1273.     struct defn *p;
  1274.     int h;
  1275.  
  1276.     if (p = lookup_define(name)) {
  1277.     if (nargs != p->nargs || strcmp(exps, p->exps) != 0) {
  1278.         char buf[200+NSIZE];
  1279.         sprintf(buf, "Redefinition of #define %s", name);
  1280.         yyerror(buf);
  1281.     }
  1282.     return;
  1283.     }
  1284.     p = (struct defn *)xalloc(sizeof(struct defn));
  1285.     p->name = xalloc(strlen(name)+1);
  1286.     strcpy(p->name, name);
  1287.     p->undef = 0;
  1288.     p->nargs = nargs;
  1289.     p->exps = xalloc(strlen(exps)+1);
  1290.     strcpy(p->exps, exps);
  1291.     h = defhash(name);
  1292.     p->next = defns[h];
  1293.     defns[h] = p;
  1294. /*fprintf(stderr, "define '%s' %d '%s'\n", name, nargs, exps);*/
  1295. }
  1296.  
  1297. static void
  1298. free_defines()
  1299. {
  1300.     struct defn *p, *q;
  1301.     int i;
  1302.  
  1303.     for(i = 0; i < DEFHASH; i++) {
  1304.     for(p = defns[i]; p; p = q) {
  1305.         q = p->next;
  1306.         free(p->name);
  1307.         free(p->exps);
  1308.         free((char *)p);
  1309.     }
  1310.     defns[i] = 0;
  1311.     }
  1312.     nexpands = 0;
  1313. }
  1314.  
  1315. struct defn *
  1316. lookup_define(s)
  1317. char *s;
  1318. {
  1319.     struct defn *p;
  1320.     int h;
  1321.  
  1322.     h = defhash(s);
  1323.     for(p = defns[h]; p; p = p->next)
  1324.     if (!p->undef && strcmp(s, p->name) == 0)
  1325.         return p;
  1326.     return 0;
  1327. }
  1328.  
  1329. #define SKIPW \
  1330.         do {\
  1331.         c = cmygetc();\
  1332.     } while(isspace(c));
  1333.  
  1334.  
  1335. /* Check if yytext is a macro and expand if it is. */
  1336. static int
  1337. expand_define()
  1338. {
  1339.     struct defn *p;
  1340.     char expbuf[DEFMAX];
  1341.     char *args[NARGS];
  1342.     char buf[DEFMAX];
  1343.     char *q, *e, *b;
  1344.  
  1345.     if (nexpands++ > EXPANDMAX) {
  1346.     lexerror("Too many macro expansions");
  1347.     return 0;
  1348.     }
  1349.     p = lookup_define(yytext);
  1350.     if (!p) {
  1351.     return 0;
  1352.     }
  1353.     if (p->nargs == -1) {
  1354.     add_input(p->exps);
  1355.     } else {
  1356.     int c, parcnt = 0, dquote = 0, squote = 0;
  1357.     int n;
  1358.     SKIPW;
  1359.     if (c != '(') {
  1360.         yyerror("Missing '(' in macro call");
  1361.         return 0;
  1362.     }
  1363.     SKIPW;
  1364.     if (c == ')')
  1365.         n = 0;
  1366.     else {
  1367.         q = expbuf;
  1368.         args[0] = q;
  1369.         for(n = 0; n < NARGS; ) {
  1370.         switch(c) {
  1371.         case '"': if (!squote) dquote ^= 1; break;
  1372.         case '\'': if (!dquote) squote ^= 1; break;
  1373.         case '(': if (!squote && !dquote) parcnt++; break;
  1374.         case ')': if (!squote && !dquote) parcnt--; break;
  1375.         case '\\': if (squote || dquote) { *q++ = c; c = mygetc();} break;
  1376.         case '\n': if (squote || dquote) { lexerror("Newline in string"); return 0; } break;
  1377.         }
  1378.         if (c == ',' && !parcnt && !dquote && !squote) {
  1379.             *q++ = 0;
  1380.             args[++n] = q;
  1381.         } else if (parcnt < 0) {
  1382.             *q++ = 0;
  1383.             n++;
  1384.             break;
  1385.         } else {
  1386.             if (c == EOF) {
  1387.             lexerror("Unexpected end of file");
  1388.             return 0;
  1389.             }
  1390.             if (q >= expbuf + DEFMAX - 5) {
  1391.             lexerror("Macro argument overflow");
  1392.             return 0;
  1393.             } else {
  1394.             *q++ = c;
  1395.             }
  1396.         }
  1397.         if (!squote && ! dquote)
  1398.             c = cmygetc();
  1399.         else
  1400.             c = mygetc();
  1401.         }
  1402.         if (n == NARGS) {
  1403.         lexerror("Maximum macro argument count exceeded");
  1404.         return 0;
  1405.         }
  1406.     }
  1407.     if (n != p->nargs) {
  1408.         yyerror("Wrong number of macro arguments");
  1409.         return 0;
  1410.     }
  1411.     /* Do expansion */
  1412.     b = buf;
  1413.     e = p->exps;
  1414.     while(*e) {
  1415.         if (*e == MARKS) {
  1416.         if (*++e == MARKS)
  1417.             *b++ = *e++;
  1418.         else {
  1419.             for(q = args[*e++ - MARKS - 1]; *q; ) {
  1420.             *b++ = *q++;
  1421.             if (b >= buf+DEFMAX) {
  1422.                 lexerror("Macro expansion overflow");
  1423.                 return 0;
  1424.             }
  1425.             }
  1426.         }
  1427.         } else {
  1428.         *b++ = *e++;
  1429.         if (b >= buf+DEFMAX) {
  1430.             lexerror("Macro expansion overflow");
  1431.             return 0;
  1432.         }
  1433.         }
  1434.     }
  1435.     *b++ = 0;
  1436.     add_input(buf);
  1437.     }
  1438.     return 1;
  1439. }
  1440.  
  1441. /* Stuff to evaluate expression.  I havn't really checked it. /LA
  1442. ** Written by "J\"orn Rennecke" <amylaar@cs.tu-berlin.de>
  1443. */
  1444. #define SKPW     do c = mygetc(); while(isspace(c)); myungetc(c)
  1445.  
  1446. static int exgetc() {
  1447.   register char c,*yyp;
  1448.  
  1449.   c=mygetc();
  1450.   while ( isalpha(c) || c=='_' ) {
  1451.     yyp=yytext;
  1452.     do {
  1453.       SAVEC;
  1454.       c=mygetc();
  1455.     } while ( isalunum(c) );
  1456.     myungetc(c);
  1457.     *yyp='\0';
  1458.     if (strcmp(yytext, "defined") == 0) {
  1459.     /* handle the defined "function" in #if */
  1460.     do c = mygetc(); while(isspace(c));
  1461.     if (c != '(') {
  1462.         yyerror("Missing ( in defined");
  1463.         continue;
  1464.     }
  1465.     do c = mygetc(); while(isspace(c));
  1466.     yyp=yytext;
  1467.     while ( isalunum(c) ) {
  1468.         SAVEC;
  1469.         c=mygetc();
  1470.     }
  1471.     *yyp='\0';
  1472.     while(isspace(c)) c = mygetc();
  1473.     if (c != ')') {
  1474.         yyerror("Missing ) in defined");
  1475.         continue;
  1476.     }
  1477.     SKPW;
  1478.     if (lookup_define(yytext))
  1479.         add_input(" 1 ");
  1480.     else
  1481.         add_input(" 0 ");
  1482.     } else {
  1483.     if (!expand_define()) add_input(" 0 ");
  1484.     }
  1485.     c=mygetc();
  1486.   }
  1487.   return c;
  1488. }
  1489.  
  1490. #define BNOT   1
  1491. #define LNOT   2
  1492. #define UMINUS 3
  1493. #define UPLUS  4
  1494.  
  1495. #define MULT   1
  1496. #define DIV    2
  1497. #define MOD    3
  1498. #define BPLUS  4
  1499. #define BMINUS 5
  1500. #define LSHIFT 6
  1501. #define RSHIFT 7
  1502. #define LESS   8
  1503. #define LEQ    9
  1504. #define GREAT 10
  1505. #define GEQ   11
  1506. #define EQ    12
  1507. #define NEQ   13
  1508. #define BAND  14
  1509. #define XOR   15
  1510. #define BOR   16
  1511. #define LAND  17
  1512. #define LOR   18
  1513. #define QMARK 19
  1514.  
  1515. static char _optab[]=
  1516. {0,4,0,0,0,26,56,0,0,0,18,14,0,10,0,22,0,0,0,0,0,0,0,0,0,0,0,0,30,50,40,74,
  1517. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,0,
  1518. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,63,0,1};
  1519. static char optab2[]=
  1520. {BNOT,0,0,LNOT,'=',NEQ,7,0,0,UMINUS,0,BMINUS,10,UPLUS,0,BPLUS,10,
  1521. 0,0,MULT,11,0,0,DIV,11,0,0,MOD,11,
  1522. 0,'<',LSHIFT,9,'=',LEQ,8,0,LESS,8,0,'>',RSHIFT,9,'=',GEQ,8,0,GREAT,8,
  1523. 0,'=',EQ,7,0,0,0,'&',LAND,3,0,BAND,6,0,'|',LOR,2,0,BOR,4,
  1524. 0,0,XOR,5,0,0,QMARK,1};
  1525. #define optab1 (_optab-' ')
  1526.  
  1527. static int cond_get_exp(priority)
  1528. int priority;
  1529. {
  1530.   int c;
  1531.   int value,value2,x;
  1532.  
  1533.   do c=exgetc(); while ( isspace(c) );
  1534.   if ( c=='(' ) {
  1535.  
  1536.     value=cond_get_exp(0);
  1537.     do c=exgetc(); while ( isspace(c) );
  1538.     if ( c!=')' ) {
  1539.       yyerror("bracket not paired in #if");
  1540.       if (!c) myungetc('\0');
  1541.     }
  1542.   } else if ( ispunct(c) ) {
  1543.     x=optab1[c];
  1544.     if (!x) {
  1545.       yyerror("illegal character in #if");
  1546.       return 0;
  1547.     }
  1548.     value=cond_get_exp(12);
  1549.     switch ( optab2[x-1] ) {
  1550.       case BNOT  : value = ~value; break;
  1551.       case LNOT  : value = !value; break;
  1552.       case UMINUS: value = -value; break;
  1553.       case UPLUS : value =  value; break;
  1554.       default :
  1555.     yyerror("illegal unary operator in #if");
  1556.     return 0;
  1557.     }
  1558.   } else {
  1559.     int base;
  1560.  
  1561.     if ( !isdigit(c) ) {
  1562.       if (!c) {
  1563.     yyerror("missing expression in #if");
  1564.     myungetc('\0');
  1565.       } else yyerror("illegal character in #if");
  1566.       return 0;
  1567.     }
  1568.     value=0;
  1569.     if ( c!='0' ) base=10;
  1570.     else {
  1571.       c=mygetc();
  1572.       if ( c=='x' || c=='X' ) {
  1573.     base=16;
  1574.     c=mygetc();
  1575.       } else base=8;
  1576.     }
  1577.     for(;;) {
  1578.       if ( isdigit(c) ) x = -'0';
  1579.       else if ( isupper(c) ) x = -'A'+10;
  1580.       else if ( islower(c) ) x = -'a'+10;
  1581.       else break;
  1582.       x+=c;
  1583.       if ( x > base ) break;
  1584.       value=value*base+x;
  1585.       c=mygetc();
  1586.     }
  1587.     myungetc(c);
  1588.   }
  1589.   for (;;) {
  1590.     do c=exgetc(); while ( isspace(c) );
  1591.     if ( !ispunct(c) ) break;
  1592.     x=optab1[c];
  1593.     if (!x) break;
  1594.     value2=mygetc();
  1595.     for(;;x+=3) {
  1596.       if ( !optab2[x] ) {
  1597.     myungetc(value2);
  1598.     if ( !optab2[x+1] ) {
  1599.       yyerror("illegal operator use in #if");
  1600.       return 0;
  1601.     }
  1602.     break;
  1603.       }
  1604.       if ( value2==optab2[x] ) break;
  1605.     }
  1606.     if ( priority >= optab2[x+2] ) {
  1607.       if( optab2[x] ) myungetc(value2);
  1608.       break;
  1609.     }
  1610.     value2=cond_get_exp(optab2[x+2]);
  1611.     switch ( optab2[x+1] ) {
  1612.       case MULT : value *= value2;    break;
  1613.       case DIV  : value /= value2;    break;
  1614.       case MOD  : value %= value2;    break;
  1615.       case BPLUS  : value += value2;    break;
  1616.       case BMINUS : value -= value2;    break;
  1617.       case LSHIFT : value <<= value2;    break;
  1618.       case RSHIFT : value >>= value2;    break;
  1619.       case LESS   : value = value <  value2;    break;
  1620.       case LEQ    : value = value <= value2;    break;
  1621.       case GREAT  : value = value >  value2;    break;
  1622.       case GEQ    : value = value >= value2;    break;
  1623.       case EQ     : value = value == value2;    break;
  1624.       case NEQ    : value = value != value2;    break;
  1625.       case BAND   : value &= value2;    break;
  1626.       case XOR    : value ^= value2;    break;
  1627.       case BOR    : value |= value2;    break;
  1628.       case LAND   : value = value && value2;    break;
  1629.       case LOR    : value = value || value2;    break;
  1630.       case QMARK  :
  1631.     do c=exgetc(); while( isspace(c) );
  1632.     if ( c!=':' ) {
  1633.       yyerror("'?' without ':' in #if");
  1634.       myungetc(c);
  1635.       return 0;
  1636.     }
  1637.     if ( value ) {
  1638.       cond_get_exp(1);
  1639.       value=value2;
  1640.     }
  1641.     else value=cond_get_exp(1);
  1642.     break;
  1643.     }
  1644.   }
  1645.   myungetc(c);
  1646.   return value;
  1647. }
  1648.  
  1649. void set_inc_list(sv)
  1650.     struct svalue *sv;
  1651. {
  1652.     int i;
  1653.     struct vector *v;
  1654.     char *p;
  1655.  
  1656.     if (sv == 0) {
  1657.     fprintf(stderr, "There must be a function 'define_include_dirs' in master.c.\n");
  1658.     fprintf(stderr, "This function should return an array of all directories to be searched\n");
  1659.     fprintf(stderr, "for include files.\n");
  1660.     exit(1);
  1661.     }
  1662.     if (sv->type != T_POINTER) {
  1663.     fprintf(stderr, "'define_include_dirs' in master.c did not return an array.\n");
  1664.     exit(1);
  1665.     }
  1666.     v = sv->u.vec;
  1667.     inc_list = (char **)xalloc(v->size * sizeof (char *));
  1668.     inc_list_size = v->size;
  1669.     for (i=0; i < v->size; i++) {
  1670.     if (v->item[i].type != T_STRING) {
  1671.         fprintf(stderr, "Illegal value returned from 'define_include_dirs' in master.c\n");
  1672.         exit(1);
  1673.     }
  1674.     p = v->item[i].u.string;
  1675.     if (*p == '/')
  1676.         p++;
  1677.     /*
  1678.      * Even make sure that the game administrator has not made an error.
  1679.      */
  1680.     if (!legal_path(p)) {
  1681.         fprintf(stderr, "'define_include_dirs' must give paths without any '..'\n");
  1682.         exit(1);
  1683.     }
  1684.     inc_list[i] = make_shared_string(p);
  1685.     }
  1686. }
  1687.